package com.ocean.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ocean.admin.entity.SysDept;
import com.ocean.admin.entity.SysUser;
import com.ocean.admin.mapper.SysDeptMapper;
import com.ocean.admin.model.dto.dept.DeptQueryDTO;
import com.ocean.admin.model.dto.dept.DeptSaveDTO;
import com.ocean.admin.model.dto.dept.DeptUpdateDTO;
import com.ocean.admin.model.vo.dept.DeptVo;
import com.ocean.admin.extension.security.core.SysUserDetails;
import com.ocean.admin.extension.security.filter.WebFilterExtend;
import com.ocean.admin.service.ISysDeptService;
import com.ocean.admin.service.ISysUserService;
import com.ocean.core.exception.verify.ApplicationException;
import com.ocean.core.util.StringUtil;
import com.ocean.core.util.constants.ConstantsAttribute;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author zhang
 * @since 2022-08-16
 */
@Service
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Autowired
    private ISysUserService iSysUserService;

    /**
     * 获取部门列表
     *
     * @param queryDTO 查询条件
     * @return 部门树
     */
    @Override
    public List<DeptVo> listTree(DeptQueryDTO queryDTO) {
        List<DeptVo> list = baseMapper.selectCustomList(queryDTO);
        if (StringUtil.isNotNull(queryDTO) && StringUtil.isNotNull(queryDTO.getDeptName())) {
            return list.stream().filter(res -> res.getDeptName().contains(queryDTO.getDeptName()))
                    .collect(Collectors.toList());
        }
        return list.stream().filter(item -> 0 == item.getParentId())
                .peek((menu) -> menu.setChildren(getChildren(menu, list)))
                .sorted(Comparator.comparingInt(menu -> (menu.getOrderNum() == null ? 0 : menu.getOrderNum())))
                .collect(Collectors.toList());
    }

    /**
     * 新增部门
     *
     * @param saveDTO 部门信息
     * @return 结果
     */
    @Override
    public String deptSave(DeptSaveDTO saveDTO) {
        Long count = baseMapper.selectCount(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptName,
                saveDTO.getDeptName()));
        if (count == 0) {
            SysDept dept = new SysDept();
            BeanUtils.copyProperties(saveDTO, dept);
            if (saveDTO.getParentId() != null) {
                SysDept sysDept = baseMapper.selectById(saveDTO.getParentId());
                dept.setAncestors(sysDept.getAncestors() + "," + dept.getParentId());
            }
            SysUserDetails current = WebFilterExtend.current();
            dept.setCreateUserId(current.getUserId());
            dept.setCreateUserName(current.getNickName());
            dept.setUpdateUserId(current.getUserId());
            dept.setUpdateUserName(current.getNickName());
            this.save(dept);
            return ConstantsAttribute.INSERT_SUCCESS;
        }
        return ConstantsAttribute.DEPT_EXISTS;
    }

    /**
     * 修改部门
     *
     * @param updateDTO 部门信息
     * @return 结果
     */
    @Override
    public String updateDept(DeptUpdateDTO updateDTO) {
        SysDept dept = new SysDept();
        this.checkDeptUpdate(updateDTO);
        BeanUtils.copyProperties(updateDTO, dept);
        SysUserDetails current = WebFilterExtend.current();
        dept.setUpdateUserName(current.getNickName());
        dept.setUpdateUserId(current.getUserId());
        this.updateById(dept);
        return ConstantsAttribute.UPDATE_SUCCESS;
    }

    /**
     * 删除部门
     *
     * @param deptId 部门ID
     * @return 结果
     */
    @Override
    public String removeDept(Long deptId) {
        this.checkDeptRemove(deptId);
        this.removeById(deptId);
        return ConstantsAttribute.REMOVE_SUCCESS;
    }


    /**
     * 部门修改校验
     *
     * @param updateDTO 部门信息
     */
    public void checkDeptUpdate(DeptUpdateDTO updateDTO) {
        SysDept sysDept = baseMapper.selectOne(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getDeptName,
                updateDTO.getDeptName()).eq(SysDept::getParentId, updateDTO.getParentId()).eq(SysDept::getDelFlag, 0));
        if (sysDept != null && !sysDept.getDeptId().equals(updateDTO.getDeptId())) {
            throw new ApplicationException("部门名称已存在，请更换");
        }
        if (updateDTO.getDeptId().equals(updateDTO.getParentId())) {
            throw new ApplicationException("上级部门不能是自己");
        }
        if (updateDTO.getStatus() == 1) {
            Long deptCount = baseMapper.selectCount(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getParentId,
                    updateDTO.getDeptId()).eq(SysDept::getStatus, 0).eq(SysDept::getDelFlag, 0));
            if (deptCount > 0) {
                throw new ApplicationException("该账户包含未停用的子部门，不能停用");
            }
        }
    }

    /**
     * 部门删除校验
     *
     * @param deptId 部门ID
     */
    public void checkDeptRemove(Long deptId) {
        Long deptCount = baseMapper.selectCount(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getParentId, deptId));
        if (deptCount > 0) {
            throw new ApplicationException("该部门存在下级部门，不能删除");
        }
        long userCount = iSysUserService.count(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId, deptId));
        if (userCount > 0) {
            throw new ApplicationException("该部门存在用户，不能删除");
        }
    }

    private List<DeptVo> getChildren(DeptVo root, List<DeptVo> all) {
        return all.stream().filter(item -> item.getParentId().equals(root.getDeptId())).peek(item -> {
            item.setChildren(getChildren(item, all));
        }).sorted(Comparator.comparingInt(menu -> (menu.getOrderNum() == null ? 0 : menu.getOrderNum()))).collect(Collectors.toList());
    }
}
